package com.kanas.webak.rbac.domain;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.codehaus.jackson.annotate.JsonIgnoreProperties;

import com.kanas.framework.persistence.DefaultOrder;
import com.kanas.framework.persistence.OrderType;
import com.kanas.framework.support.AbstractModel;
import com.kanas.framework.util.StringUtils;
import com.kanas.webak.admin.domain.AppUser;

@Entity
@Table(name = "kanas_rbac_role")
@JsonIgnoreProperties({"users","functions","permissions","mutex","inclusionRoles","extensionRoles","userRoles"})
public class AppRole extends AbstractModel implements Cloneable { 

	public static String ROLE_PREFIX="ROLE_";
	
	@Transient
	private static final long serialVersionUID = 1L;
	
	@Transient Boolean selected=false;
	
	@Id
	@Column(name = "id", length = 32)
	private String id;
	
	@Column(name = "label", length =100)
	private String label;
	@Column(name = "admin_flag", length = 1)
	private Boolean adminFlag = false;
	@Column(name = "enable_flag", length = 1)
	private Boolean enableFlag;
	@Column(name = "export_flag", length = 1)
	private Boolean exportFlag;
	@Column(name = "description", length =200)
	private String description;
	
	@DefaultOrder(OrderType.ASC)
	@Column(name = "sort_number")
	private Integer sortNumber;

	@OneToMany(mappedBy = "role", cascade = {CascadeType.ALL}, fetch = FetchType.LAZY)
	private Set<AppPermission> permissions;
	
	@ManyToMany(cascade = {CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REFRESH}, fetch = FetchType.LAZY)   
	@JoinTable(name = "kanas_rbac_user_role",
	joinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"),
	inverseJoinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"))
	private Set<AppUser> users;
	
	@ManyToMany(cascade = {CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REFRESH}, fetch = FetchType.LAZY)   
	@JoinTable(name = "kanas_rbac_role_inherits",
	joinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"),
	inverseJoinColumns = @JoinColumn(name = "include_role_id", referencedColumnName = "id"))
	private Set<AppRole> inclusionRoles;

	@ManyToMany(mappedBy="inclusionRoles",cascade = {CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REFRESH}, fetch = FetchType.LAZY)
	private Set<AppRole> extensionRoles;

	@OneToMany(mappedBy = "role", cascade = {CascadeType.ALL}, fetch = FetchType.LAZY)
	private Set<AppUserRole> userRoles;
	
	@ManyToMany(cascade = {CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REFRESH}, fetch = FetchType.LAZY)   
	@JoinTable(name = "kanas_rbac_role_mutex_x",
	joinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"),
	inverseJoinColumns = @JoinColumn(name = "mutex_id", referencedColumnName = "id"))
	private Set<Mutex> mutex;

	@Transient
	private String appendix;
	@Transient
	private Boolean checked;
	
	public AppRole() {
		this.id = StringUtils.generateUUID();
	}
	
	public String getId() {
		return id;
	}
	public String getLabel() {
		return label;
	}

	public void setLabel(String label) {
		this.label = label;
	}

	public void setId(String id) {
		this.id = id;
	}
	
	public Set<AppPermission> getPermissions() {
		if(permissions == null) permissions = new HashSet<AppPermission>();
		return permissions;
	}

	public void setPermissions(Set<AppPermission> permisstions) {
		this.permissions = permisstions;
	}

	public Set<AppUser> getUsers() {
		if(users == null) users = new HashSet<AppUser>();
		return users;
	}

	public Set<AppUserRole> getUserRoles() {
		if(userRoles == null) userRoles = new HashSet<AppUserRole>();
		return userRoles;
	}

	public void setUserRoles(Set<AppUserRole> userRoles) {
		this.userRoles = userRoles;
	}

	public void setAdminFlag(Boolean adminFlag) {
		this.adminFlag = adminFlag;
	}

	public Boolean getAdminFlag() {
		return adminFlag;
	}

	public void setUsers(Set<AppUser> users){
		this.users = users;
	}
	
	public String getAppendix() {
		return appendix;
	}

	public void setAppendix(String appendix) {
		this.appendix = appendix;
	}

	public Integer getSortNumber() {
		return sortNumber;
	}

	public void setSortNumber(Integer sortNumber) {
		this.sortNumber = sortNumber;
	}

	public Boolean getEnableFlag() {
		return enableFlag;
	}

	public void setEnableFlag(Boolean enableFlag) {
		this.enableFlag = enableFlag;
	}

	public Boolean getExportFlag() {
		return exportFlag;
	}

	public void setExportFlag(Boolean exportFlag) {
		this.exportFlag = exportFlag;
	}

	public Set<AppRole> getInclusionRoles() {
		if(inclusionRoles == null) inclusionRoles = new HashSet<AppRole>();
		return inclusionRoles;
	}

	public void setInclusionRoles(Set<AppRole> inclusionRoles) {
		this.inclusionRoles = inclusionRoles;
	}

	public Set<AppRole> getExtensionRoles() {
		return extensionRoles;
	}

	public void setExtensionRoles(Set<AppRole> extensionRoles) {
		this.extensionRoles = extensionRoles;
	}

	public Set<Mutex> getMutex() {
		return mutex;
	}

	public void setMutex(Set<Mutex> mutex) {
		this.mutex = mutex;
	}

	public String getDescription() {
		if(description == null) description = "";
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public Boolean getSelected() {
		return selected;
	}

	public void setSelected(Boolean selected) {
		this.selected = selected;
	}
	
	@Override
	public String toIdString() {
		return id;
	}

	public Boolean getChecked() {
		if(checked == null) checked = false;
		return checked;
	}

	public void setChecked(Boolean checked) {
		this.checked = checked;
	}

}